<!DOCTYPE html>
<html lang="zh-CN">





<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/blog/img/favicon.png">
  <link rel="icon" type="image/png" href="/blog/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  
  <meta name="theme-color" content="#35495e">
  <meta name="description" content="小菜头的博客，主要记录学习笔记，包含：html,css,javascript,jQuery,vue等">
  <meta name="author" content="A-cai">
  <meta name="keywords" content="html,css,javascript,jQuery,vue">
  <title>JavaSciprt - A-cai的blog</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/blog/lib/hint/hint.min.css" />

  
    <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/atom-one-dark.min.css" />
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_yg9cfy8wd6.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_pjno9b9zyxs.css">


<link  rel="stylesheet" href="/blog/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/blog/js/utils.js" ></script>
<meta name="generator" content="Hexo 4.2.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/blog/">&nbsp;<strong>A-cai的学习笔记</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/blog/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container text-center white-text fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              
  <div class="mt-3 post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2020-06-26 14:04">
      2020年6月26日 下午
    </time>
  </div>


<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      7.5k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      90
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <div class="post-content mx-auto" id="post">
            
              <p class="note note-info">
                
                  本文最后更新于：2020年3月6日 下午
                
              </p>
            
            <article class="markdown-body">
              <h1 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h1><p>同源策略</p>
<p>同源策略可防止 JavaScript 发起跨域请求。源被定义为 URI、主机名和端口号的组合。此策略可防止页面上的恶意脚本通过该页面的文档对象模型，访问另一个网页上的敏感数据。</p>
<h4 id="回到顶部"><a href="#回到顶部" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="跨域"><a href="#跨域" class="headerlink" title="跨域"></a>跨域</h2><ul>
<li>原因 <br><br>浏览器的同源策略导致了跨域</li>
<li>作用 <br><br>用于隔离潜在恶意文件的重要安全机制</li>
<li>解决</li>
</ul>
<ol>
<li>jsonp ，允许 script 加载第三方资源</li>
<li>反向代理（nginx 服务内部配置 Access-Control-Allow-Origin *）</li>
<li>cors 前后端协作设置请求头部，Access-Control-Allow-Origin 等头部信息</li>
<li>iframe 嵌套通讯，postmessage</li>
</ol>
<p><a href="https://zhuanlan.zhihu.com/p/41479807" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/41479807</a> <br><br><a href="http://www.ruanyifeng.com/blog/2016/04/cors.html" target="_blank" rel="noopener">跨域资源共享 CORS 阮一峰</a></p>
<h4 id="回到顶部-1"><a href="#回到顶部-1" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="JSONP"><a href="#JSONP" class="headerlink" title="JSONP"></a>JSONP</h2><p>这是我认为写得比较通俗易懂的一篇文章 直接转载过来<br><br><a href="https://blog.csdn.net/hansexploration/article/details/80314948" target="_blank" rel="noopener">https://blog.csdn.net/hansexploration/article/details/80314948</a></p>
<h4 id="回到顶部-2"><a href="#回到顶部-2" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="域名收敛"><a href="#域名收敛" class="headerlink" title="域名收敛"></a>域名收敛</h2><p>PC 时代为了突破浏览器的域名并发限制。有了域名发散。<br><br>浏览器有并发限制，是为了防止DDOS攻击。<br><br>域名收敛：就是将静态资源放在一个域名下。减少DNS解析的开销。<br><br>域名发散：是将静态资源放在多个子域名下，就可以多线程下载，提高并行度，使客户端加载静态资源更加迅速。<br><br>域名发散是pc端为了利用浏览器的多线程并行下载能力。而域名收敛多用与移动端，提高性能，因为dns解析是是从后向前迭代解析，如果域名过多性能会下降，增加DNS的解析开销。</p>
<h4 id="回到顶部-3"><a href="#回到顶部-3" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="事件绑定的方式"><a href="#事件绑定的方式" class="headerlink" title="事件绑定的方式"></a>事件绑定的方式</h2><ul>
<li><p>嵌入dom</p>
<div class="hljs"><pre><code class="hljs hsp">&lt;<span class="hljs-keyword">button</span> <span class="hljs-keyword">onclick</span>=<span class="hljs-string">"func()"</span>&gt;按钮&lt;/<span class="hljs-keyword">button</span>&gt;</code></pre></div>
</li>
<li><p>直接绑定</p>
<div class="hljs"><pre><code class="hljs actionscript">btn.onclick = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>&#123;&#125;</code></pre></div>
</li>
<li><p>事件监听</p>
<div class="hljs"><pre><code class="hljs actionscript">btn.addEventListener(<span class="hljs-string">'click'</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>&#123;&#125;)</code></pre></div>

</li>
</ul>
<h4 id="回到顶部-4"><a href="#回到顶部-4" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="事件委托"><a href="#事件委托" class="headerlink" title="事件委托"></a>事件委托</h2><p>事件委托利用了事件冒泡，只指定一个事件处理程序，就可以管理某一类型的所有事件。所有用到按钮的事件（多数鼠标事件和键盘事件）都适合采用事件委托技术，<br>使用事件委托可以节省内存。</p>
<div class="hljs"><pre><code class="hljs xquery"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span></span>
<span class="xml">  </span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>苹果<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
<span class="xml">  </span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>香蕉<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
<span class="xml">  </span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>凤梨<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>

// good
<span class="hljs-keyword">document</span>.querySelector('ul').onclick = (event) =&gt; &#123;
  <span class="hljs-keyword">let</span> target = event.target
  <span class="hljs-keyword">if</span> (target.nodeName === <span class="hljs-string">'LI'</span>) &#123;
    console.log(target.innerHTML)
  &#125;
&#125;

// bad
<span class="hljs-keyword">document</span>.querySelectorAll('li').forEach((e) =&gt; &#123;
  e.onclick = <span class="hljs-keyword">function</span>() &#123;
    console.log(this.innerHTML)
  &#125;
&#125;)</code></pre></div>

<h4 id="回到顶部-5"><a href="#回到顶部-5" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="事件循环"><a href="#事件循环" class="headerlink" title="事件循环"></a>事件循环</h2><p>事件循环是一个单线程循环，用于监视调用堆栈并检查是否有工作即将在任务队列中完成。如果调用堆栈为空并且任务队列中有回调函数，则将回调函数出队并推送到调用堆栈中执行。</p>
<h4 id="回到顶部-6"><a href="#回到顶部-6" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="事件模型"><a href="#事件模型" class="headerlink" title="事件模型"></a>事件模型</h2><ul>
<li><p>DOM0<br><br>直接绑定</p>
<div class="hljs"><pre><code class="hljs actionscript">&lt;input onclick=<span class="hljs-string">"sayHi()"</span>/&gt;

btn.onclick = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>&#123;&#125;
btn.onclick = <span class="hljs-literal">null</span></code></pre></div>
</li>
<li><p>DOM2<br><br>DOM2级事件可以冒泡和捕获<br>通过addEventListener绑定<br>通过removeEventListener解绑</p>
<div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-comment">// 绑定</span>
btn.add<span class="hljs-constructor">EventListener('<span class="hljs-params">click</span>', <span class="hljs-params">sayHi</span>)</span>
<span class="hljs-comment">// 解绑</span>
btn.remove<span class="hljs-constructor">EventListener('<span class="hljs-params">click</span>', <span class="hljs-params">sayHi</span>)</span></code></pre></div>
</li>
<li><p>DOM3<br><br>DOM3具有更多事件类型<br>DOM3级事件在DOM2级事件的基础上添加了更多的事件类型，全部类型如下：</p>
<div class="hljs"><pre><code class="hljs autoit">UI事件，当用户与页面上的元素交互时触发，如：load、scroll
焦点事件，当元素获得或失去焦点时触发，如：blur、focus
鼠标事件，当用户通过鼠标在页面执行操作时触发如：dbclick、<span class="hljs-built_in">mouseup</span>
滚轮事件，当使用鼠标滚轮或类似设备时触发，如：<span class="hljs-built_in">mousewheel</span>
文本事件，当在文档中输入文本时触发，如：textInput
键盘事件，当用户通过键盘在页面上执行操作时触发，如：keydown、keypress
合成事件，当为IME（输入法编辑器）输入字符时触发，如：compositionstart
变动事件，当底层DOM结构发生变化时触发，如：DOMsubtreeModified</code></pre></div>

</li>
</ul>
<p><a href="https://www.jianshu.com/p/3acdf5f71d5b" target="_blank" rel="noopener">https://www.jianshu.com/p/3acdf5f71d5b</a></p>
<h4 id="回到顶部-7"><a href="#回到顶部-7" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="如何自定义事件"><a href="#如何自定义事件" class="headerlink" title="如何自定义事件"></a>如何自定义事件</h2><ol>
<li>原生提供了3个方法实现自定义事件</li>
<li>createEvent，设置事件类型，是 html 事件还是 鼠标事件</li>
<li>initEvent 初始化事件，事件名称，是否允许冒泡，是否阻止自定义事件</li>
<li>dispatchEvent 触发事件</li>
</ol>
<p><a href="https://developer.mozilla.org/zh-CN/docs/Web/Guide/Events/Creating_and_triggering_events" target="_blank" rel="noopener">MDN</a></p>
<h4 id="回到顶部-8"><a href="#回到顶部-8" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="target和currentTarget区别"><a href="#target和currentTarget区别" class="headerlink" title="target和currentTarget区别"></a>target和currentTarget区别</h2><ul>
<li>event.target<br><br>返回触发事件的元素</li>
<li>event.currentTarget<br><br>返回绑定事件的元素#JavaScript)</li>
</ul>
<h2 id="prototype和proto的关系是什么"><a href="#prototype和proto的关系是什么" class="headerlink" title="prototype和proto的关系是什么"></a>prototype和<strong>proto</strong>的关系是什么</h2><p>所有的对象都拥有<strong>proto</strong>属性，它指向对象构造函数的prototype属性</p>
<div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-keyword">let</span> obj = &#123;&#125;
obj.__proto__<span class="hljs-operator"> === </span><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Object</span>.</span></span>prototype <span class="hljs-comment">// true</span>

<span class="hljs-keyword">function</span> <span class="hljs-constructor">Test()</span>&#123;&#125;
test.__proto__<span class="hljs-operator"> == </span><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Test</span>.</span></span>prototype <span class="hljs-comment">// true</span></code></pre></div>

<p>所有的函数都同时拥有<strong>proto</strong>和protytpe属性<br>函数的<strong>proto</strong>指向自己的函数实现 函数的protytpe是一个对象 所以函数的prototype也有<strong>proto</strong>属性 指向Object.prototype</p>
<div class="hljs"><pre><code class="hljs autoit">function <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> &#123;&#125;</span>
<span class="hljs-function"><span class="hljs-keyword">func</span>.<span class="hljs-title">prototype</span>.<span class="hljs-title">__proto__</span> === <span class="hljs-title">Object</span>.<span class="hljs-title">prototype</span> // <span class="hljs-title">true</span></span></code></pre></div>

<p>Object.prototype.<strong>proto</strong>指向null</p>
<div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Object</span>.</span></span>prototype.__proto__ <span class="hljs-comment">// null</span></code></pre></div>

<h4 id=""><a href="#" class="headerlink" title=""></a></h4><h2 id="原型继承"><a href="#原型继承" class="headerlink" title="原型继承"></a>原型继承</h2><p>所有的JS对象都有一个prototype属性，指向它的原型对象。当试图访问一个对象的属性时，如果没有在该对象上找到，它还会搜寻该对象的原型，以及该对象的原型的原型，依次层层向上搜索，直到找到一个名字匹配的属性或到达原型链的末尾。</p>
<h4 id="回到顶部-9"><a href="#回到顶部-9" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><p>JS高程第3版 第6章 继承<br>寄生组合式继承</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SuperType</span>(<span class="hljs-params">name</span>) </span>&#123;
    <span class="hljs-keyword">this</span>.name = name
    <span class="hljs-keyword">this</span>.colors = [<span class="hljs-string">'red'</span>]
&#125;

SuperType.prototype.sayName = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.name)
&#125;
<span class="hljs-comment">// 继承实例属性</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SubType</span>(<span class="hljs-params">name, age</span>) </span>&#123;
    SuperType.call(<span class="hljs-keyword">this</span>, name)
    <span class="hljs-keyword">this</span>.age = age
&#125;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">inheritPrototype</span>(<span class="hljs-params">subType, superType</span>) </span>&#123;
    <span class="hljs-keyword">let</span> prototype = <span class="hljs-built_in">Object</span>.create(superType.prototype)
    prototype.constructor = subType
    subType.prototype = prototype
&#125;
<span class="hljs-comment">// 继承原型方法</span>
inheritPrototype(SubType, SuperType)

<span class="hljs-comment">// 定义自己的原型方法</span>
SubType.prototype.sayAge = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.age)
&#125;</code></pre></div>

<h4 id="回到顶部-10"><a href="#回到顶部-10" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h2><p>闭包是指有权访问另一个函数作用域中的变量的函数。</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHi</span>(<span class="hljs-params">name</span>) </span>&#123;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> &#123;
       <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hi! <span class="hljs-subst">$&#123;name&#125;</span>`</span>)
    &#125;
&#125;
<span class="hljs-keyword">const</span> test = sayHi(<span class="hljs-string">'xiaoming'</span>)
test() <span class="hljs-comment">// Hi! xiaoming</span></code></pre></div>
<p>虽然sayHi函数已经执行完毕，但是其活动对象也不会被销毁，因为test函数仍然引用着sayHi函数中的变量name，这就是闭包。<br><br>但也因为闭包引用着另一个函数的变量，导致另一个函数已经不使用了也无法销毁，所以闭包使用过多，会占用较多的内存，这也是一个副作用，内存泄漏。</p>
<h4 id="回到顶部-11"><a href="#回到顶部-11" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="有一个函数，参数是一个函数，返回值也是一个函数，返回的函数功能和入参的函数相似，但这个函数只能执行3次，再次执行无效，如何实现"><a href="#有一个函数，参数是一个函数，返回值也是一个函数，返回的函数功能和入参的函数相似，但这个函数只能执行3次，再次执行无效，如何实现" class="headerlink" title="有一个函数，参数是一个函数，返回值也是一个函数，返回的函数功能和入参的函数相似，但这个函数只能执行3次，再次执行无效，如何实现"></a>有一个函数，参数是一个函数，返回值也是一个函数，返回的函数功能和入参的函数相似，但这个函数只能执行3次，再次执行无效，如何实现</h2><p>这个题目是考察闭包的使用</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHi</span>(<span class="hljs-params"></span>) </span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'hi'</span>)
&#125;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">threeTimes</span>(<span class="hljs-params">fn</span>) </span>&#123;
    <span class="hljs-keyword">let</span> times = <span class="hljs-number">0</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> &#123;
        <span class="hljs-keyword">if</span> (times++ &lt; <span class="hljs-number">3</span>) &#123;
            fn()
        &#125;
    &#125;
&#125;

<span class="hljs-keyword">const</span> newFn = threeTimes(sayHi)
newFn()
newFn()
newFn()
newFn()
newFn() <span class="hljs-comment">// 后面两次执行都无任何反应</span></code></pre></div>
<p>通过闭包变量 <code>times</code> 来控制函数的执行</p>
<h4 id="回到顶部-12"><a href="#回到顶部-12" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="实现add函数-让add-a-b-和add-a-b-两种调用结果相同"><a href="#实现add函数-让add-a-b-和add-a-b-两种调用结果相同" class="headerlink" title="实现add函数,让add(a)(b)和add(a,b)两种调用结果相同"></a>实现add函数,让add(a)(b)和add(a,b)两种调用结果相同</h2><div class="hljs"><pre><code class="hljs actionscript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-params">(a, b)</span> </span>&#123;
    <span class="hljs-keyword">if</span> (b === <span class="hljs-literal">undefined</span>) &#123;
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(x)</span> </span>&#123;
            <span class="hljs-keyword">return</span> a + x
        &#125;
    &#125;

    <span class="hljs-keyword">return</span> a + b
&#125;</code></pre></div>
<h4 id="回到顶部-13"><a href="#回到顶部-13" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="Ajax"><a href="#Ajax" class="headerlink" title="Ajax"></a>Ajax</h2><p>Ajax(asynchronous JavaScript and XML)是使用客户端上的许多 Web 技术，创建异步 Web 应用的一种 Web 开发技术。借助 Ajax，Web 应用可以异步（在后台）向服务器发送数据和从服务器检索数据，而不会干扰现有页面的显示和行为。通过将数据交换层与表示层分离，Ajax 允许网页和扩展 Web 应用程序动态更改内容，而无需重新加载整个页面。实际上，现在通常将 JSON 替换为 XML，因为 JavaScript 对 JSON 有原生支持优势。<br><br>XMLHttpRequest API 经常用于异步通信。此外还有最近流行的fetch API。</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">let</span> xmlhttp
<span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.XMLHttpRequest) &#123;
	<span class="hljs-comment">//  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码</span>
	xmlhttp = <span class="hljs-keyword">new</span> XMLHttpRequest()
&#125; <span class="hljs-keyword">else</span> &#123;
	<span class="hljs-comment">// IE6, IE5 浏览器执行代码</span>
	xmlhttp = <span class="hljs-keyword">new</span> ActiveXObject(<span class="hljs-string">"Microsoft.XMLHTTP"</span>)
&#125;
xmlhttp.onreadystatechange = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> &#123;
	<span class="hljs-keyword">if</span> (xmlhttp.readyState === <span class="hljs-number">4</span> &amp;&amp; xmlhttp.status === <span class="hljs-number">200</span>) &#123;
		<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"myDiv"</span>).innerHTML = xmlhttp.responseText
	&#125;
&#125;
xmlhttp.open(<span class="hljs-string">"GET"</span>, <span class="hljs-string">"/ajax/test.txt"</span>, <span class="hljs-literal">true</span>)
xmlhttp.send()</code></pre></div>
<h4 id="回到顶部-14"><a href="#回到顶部-14" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="使用Ajax的优缺点分别是什么"><a href="#使用Ajax的优缺点分别是什么" class="headerlink" title="使用Ajax的优缺点分别是什么"></a>使用Ajax的优缺点分别是什么</h2><p><strong>优点</strong></p>
<ul>
<li>交互性更好。来自服务器的新内容可以动态更改，无需重新加载整个页面。</li>
<li>减少与服务器的连接，因为脚本和样式只需要被请求一次。</li>
<li>状态可以维护在一个页面上。JavaScript 变量和 DOM 状态将得到保持，因为主容器页面未被重新加载。</li>
<li>基本上包括大部分 SPA 的优点。</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>动态网页很难收藏。</li>
<li>如果 JavaScript 已在浏览器中被禁用，则不起作用。</li>
<li>有些网络爬虫不执行 JavaScript，也不会看到 JavaScript 加载的内容。</li>
<li>基本上包括大部分 SPA 的缺点。 搜索引擎优化比较难</li>
</ul>
<p><a href="https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questions.md" target="_blank" rel="noopener">https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questions.md</a></p>
<h4 id="回到顶部-15"><a href="#回到顶部-15" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="Ajax和Fetch区别"><a href="#Ajax和Fetch区别" class="headerlink" title="Ajax和Fetch区别"></a>Ajax和Fetch区别</h2><ul>
<li>ajax是使用XMLHttpRequest对象发起的，但是用起来很麻烦，所以ES6新规范就有了fetch，fetch发一个请求不用像ajax那样写一大堆代码。</li>
<li>使用fetch无法取消一个请求，这是因为fetch基于Promise，而Promise无法做到这一点。</li>
<li>在默认情况下，fetch不会接受或者发送cookies</li>
<li>fetch没有办法原生监测请求的进度，而XMLHttpRequest可以</li>
<li>fetch只对网络请求报错，对400，500都当做成功的请求，需要封装去处理</li>
<li>fetch由于是ES6规范，兼容性上比不上XMLHttpRequest</li>
</ul>
<h4 id="回到顶部-16"><a href="#回到顶部-16" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="变量提升"><a href="#变量提升" class="headerlink" title="变量提升"></a>变量提升</h2><p>var会使变量提升，这意味着变量可以在声明之前使用。let和const不会使变量提升，提前使用会报错。<br>变量提升（hoisting）是用于解释代码中变量声明行为的术语。使用var关键字声明或初始化的变量，会将声明语句“提升”到当前作用域的顶部。 但是，只有声明才会触发提升，赋值语句（如果有的话）将保持原样。</p>
<div class="hljs"><pre><code class="hljs javascript">functiontest()&#123;
 <span class="hljs-keyword">var</span> num=<span class="hljs-number">123</span>;
 <span class="hljs-built_in">console</span>.log(num);
&#125;
test();<span class="hljs-comment">//123</span>
<span class="hljs-built_in">console</span>.log(num);<span class="hljs-comment">//报错</span></code></pre></div>





<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> str= <span class="hljs-string">"我是MT"</span>;
test();
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">test</span>(<span class="hljs-params"></span>) </span>&#123;
    <span class="hljs-keyword">var</span> str
    <span class="hljs-built_in">console</span>.log(str);<span class="hljs-comment">//undefined</span>
    <span class="hljs-keyword">var</span> str= <span class="hljs-string">"哈哈哈"</span>;
    <span class="hljs-built_in">console</span>.log(str); <span class="hljs-comment">//hahaha</span>
<span class="hljs-built_in">console</span>.log(str);     <span class="hljs-comment">//</span></code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">test</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-keyword">if</span>(<span class="hljs-string">"a"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>)&#123;
        <span class="hljs-keyword">var</span> a = <span class="hljs-number">10</span>;
    &#125;
    <span class="hljs-built_in">console</span>.log(a);   
&#125;

test()</code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">if</span>(<span class="hljs-string">"a"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>)&#123;
    <span class="hljs-keyword">var</span> a = <span class="hljs-number">10</span>;
&#125;
<span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">//10</span></code></pre></div>



<h2 id="使用let、var和const创建变量有什么区别"><a href="#使用let、var和const创建变量有什么区别" class="headerlink" title="使用let、var和const创建变量有什么区别"></a>使用let、var和const创建变量有什么区别</h2><p>用var声明的变量的作用域是它当前的执行上下文，它可以是嵌套的函数，也可以是声明在任何函数外的变量。let和const是块级作用域，意味着它们只能在最近的一组花括号（function、if-else 代码块或 for 循环中）中访问。</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params"></span>) </span>&#123;
  <span class="hljs-comment">// 所有变量在函数中都可访问</span>
  <span class="hljs-keyword">var</span> bar = <span class="hljs-string">'bar'</span>;
  <span class="hljs-keyword">let</span> baz = <span class="hljs-string">'baz'</span>;
  <span class="hljs-keyword">const</span> qux = <span class="hljs-string">'qux'</span>;

  <span class="hljs-built_in">console</span>.log(bar); <span class="hljs-comment">// bar</span>
  <span class="hljs-built_in">console</span>.log(baz); <span class="hljs-comment">// baz</span>
  <span class="hljs-built_in">console</span>.log(qux); <span class="hljs-comment">// qux</span>
&#125;

<span class="hljs-built_in">console</span>.log(bar); <span class="hljs-comment">// ReferenceError: bar is not defined</span>
<span class="hljs-built_in">console</span>.log(baz); <span class="hljs-comment">// ReferenceError: baz is not defined</span>
<span class="hljs-built_in">console</span>.log(qux); <span class="hljs-comment">// ReferenceError: qux is not defined</span></code></pre></div>

<div class="hljs"><pre><code class="hljs js"><span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) &#123;
  <span class="hljs-keyword">var</span> bar = <span class="hljs-string">'bar'</span>;
  <span class="hljs-keyword">let</span> baz = <span class="hljs-string">'baz'</span>;
  <span class="hljs-keyword">const</span> qux = <span class="hljs-string">'qux'</span>;
&#125;

<span class="hljs-comment">// 用 var 声明的变量在函数作用域上都可访问</span>
<span class="hljs-built_in">console</span>.log(bar); <span class="hljs-comment">// bar</span>
<span class="hljs-comment">// let 和 const 定义的变量在它们被定义的语句块之外不可访问</span>
<span class="hljs-built_in">console</span>.log(baz); <span class="hljs-comment">// ReferenceError: baz is not defined</span>
<span class="hljs-built_in">console</span>.log(qux); <span class="hljs-comment">// ReferenceError: qux is not defined</span></code></pre></div>

<p>var会使变量提升，这意味着变量可以在声明之前使用。let和const不会使变量提升，提前使用会报错。</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-built_in">console</span>.log(foo); <span class="hljs-comment">// undefined</span>

<span class="hljs-keyword">var</span> foo = <span class="hljs-string">'foo'</span>;

<span class="hljs-built_in">console</span>.log(baz); <span class="hljs-comment">// ReferenceError: can't access lexical declaration 'baz' before initialization</span>

<span class="hljs-keyword">let</span> baz = <span class="hljs-string">'baz'</span>;

<span class="hljs-built_in">console</span>.log(bar); <span class="hljs-comment">// ReferenceError: can't access lexical declaration 'bar' before initialization</span>

<span class="hljs-keyword">const</span> bar = <span class="hljs-string">'bar'</span>;</code></pre></div>

<p>用var重复声明不会报错，但let和const会。</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-keyword">var</span> foo = <span class="hljs-string">'foo'</span>;
<span class="hljs-keyword">var</span> foo = <span class="hljs-string">'bar'</span>;
<span class="hljs-built_in">console</span>.log(foo); <span class="hljs-comment">// "bar"</span>

<span class="hljs-keyword">let</span> baz = <span class="hljs-string">'baz'</span>;
<span class="hljs-keyword">let</span> baz = <span class="hljs-string">'qux'</span>; <span class="hljs-comment">// Uncaught SyntaxError: Identifier 'baz' has already been declared</span></code></pre></div>

<p>let和const的区别在于：let允许多次赋值，而const只允许一次。</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-comment">// 这样不会报错。</span>
<span class="hljs-keyword">let</span> foo = <span class="hljs-string">'foo'</span>;
foo = <span class="hljs-string">'bar'</span>;

<span class="hljs-comment">// 这样会报错。</span>
<span class="hljs-keyword">const</span> baz = <span class="hljs-string">'baz'</span>;
baz = <span class="hljs-string">'qux'</span>;</code></pre></div>

<h4 id="-1"><a href="#-1" class="headerlink" title=""></a></h4><h2 id="对象浅拷贝和深拷贝有什么区别"><a href="#对象浅拷贝和深拷贝有什么区别" class="headerlink" title="对象浅拷贝和深拷贝有什么区别"></a>对象浅拷贝和深拷贝有什么区别</h2><p>let stu = {name:”xiaoming”,teacher:{name:”laochen”}}</p>
<p>let newobj = {}</p>
<p>for key in stu</p>
<p>​    newobj[key] = stu[key]</p>
<p>let s1 = newobj</p>
<p>在 <code>JS</code> 中，除了基本数据类型，还存在对象、数组这种引用类型。<br>基本数据类型，拷贝是直接拷贝变量的值，而引用类型拷贝的其实是变量的地址。</p>
<div class="hljs"><pre><code class="hljs nix"><span class="hljs-keyword">let</span> <span class="hljs-attr">o1</span> = &#123;a: <span class="hljs-number">1</span>&#125;
<span class="hljs-keyword">let</span> <span class="hljs-attr">o2</span> = o1</code></pre></div>
<p>在这种情况下，如果改变 <code>o1</code> 或 <code>o2</code> 其中一个值的话，另一个也会变，因为它们都指向同一个地址。</p>
<div class="hljs"><pre><code class="hljs livecodeserver">o2.<span class="hljs-keyword">a</span> = <span class="hljs-number">3</span>
console.<span class="hljs-built_in">log</span>(o1.<span class="hljs-keyword">a</span>)<span class="hljs-comment"> // 3</span></code></pre></div>
<p>而浅拷贝和深拷贝就是在这个基础之上做的区分，如果在拷贝这个对象的时候，只对基本数据类型进行了拷贝，而对引用数据类型只是进行了引用的传递，而没有重新创建一个新的对象，则认为是浅拷贝。反之，在对引用数据类型进行拷贝的时候，创建了一个新的对象，并且复制其内的成员变量，则认为是深拷贝。</p>
<h4 id="回到顶部-17"><a href="#回到顶部-17" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="怎么实现对象深拷贝"><a href="#怎么实现对象深拷贝" class="headerlink" title="怎么实现对象深拷贝"></a>怎么实现对象深拷贝</h2><div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-keyword">let</span> o1 = &#123;a:&#123;
    b:<span class="hljs-number">1</span>
  &#125;
&#125;
<span class="hljs-keyword">let</span> o2 = <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">JSON</span>.</span></span>parse(<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">JSON</span>.</span></span>stringify(o1))</code></pre></div>
<p>另一种方法</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deepCopy</span>(<span class="hljs-params">s</span>) </span>&#123;
    <span class="hljs-keyword">const</span> d = &#123;&#125;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> k <span class="hljs-keyword">in</span> s) &#123;
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> s[k] == <span class="hljs-string">'object'</span>) &#123;
            d[k] = deepCopy(s[k])
        &#125; <span class="hljs-keyword">else</span> &#123;
            d[k] = s[k]
        &#125;
    &#125;

    <span class="hljs-keyword">return</span> d
&#125;</code></pre></div>
<h4 id="回到顶部-18"><a href="#回到顶部-18" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="数组去重"><a href="#数组去重" class="headerlink" title="数组去重"></a>数组去重</h2><p>ES5</p>
<div class="hljs"><pre><code class="hljs pgsql"><span class="hljs-keyword">function</span> <span class="hljs-keyword">unique</span>(arry) &#123;
    const <span class="hljs-keyword">temp</span> = []
    arry.<span class="hljs-keyword">forEach</span>(e =&gt; &#123;
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">temp</span>.indexOf(e) == <span class="hljs-number">-1</span>) &#123;
            <span class="hljs-keyword">temp</span>.push(e)
        &#125;
    &#125;)
    
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">temp</span>
&#125;</code></pre></div>
<p>ES6</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unique</span> (<span class="hljs-params">arr</span>) </span>&#123;
   <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.from(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>(arr))
&#125;</code></pre></div>


<h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><ol>
<li>Undefined </li>
<li>Null </li>
<li>Boolean </li>
<li>Number</li>
<li>String </li>
<li>Object</li>
<li>symbol(ES6新增)</li>
</ol>
<h2 id="内置函数-原生函数"><a href="#内置函数-原生函数" class="headerlink" title="内置函数(原生函数)"></a>内置函数(原生函数)</h2><ul>
<li>String</li>
<li>Number</li>
<li>Boolean</li>
<li>Object</li>
<li>Function</li>
<li>Array</li>
<li>Date</li>
<li>RegExp</li>
<li>Error</li>
<li>Symbol</li>
</ul>
<p>原始值 “I am a string” 并不是一个对象，它只是一个字面量，并且是一个不可变的值。<br>如果要在这个字面量上执行一些操作，比如获取长度、访问其中某个字符等，那需要将其<br>转换为 String 对象。<br>幸好，在必要时语言会自动把字符串字面量转换成一个 String 对象，也就是说你并不需要<br>显式创建一个对象。</p>
<h4 id="回到顶部-19"><a href="#回到顶部-19" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="如何判断数组与对象"><a href="#如何判断数组与对象" class="headerlink" title="如何判断数组与对象"></a>如何判断数组与对象</h2><div class="hljs"><pre><code class="hljs js"><span class="hljs-built_in">Array</span>.isArray([]) <span class="hljs-comment">// true</span>
<span class="hljs-built_in">Array</span>.isArray(&#123;&#125;) <span class="hljs-comment">// false</span>

<span class="hljs-keyword">typeof</span> [] <span class="hljs-comment">// "object"</span>
<span class="hljs-keyword">typeof</span> &#123;&#125; <span class="hljs-comment">// "object"</span>

<span class="hljs-built_in">Object</span>.prototype == [].__proto__ <span class="hljs-comment">// false</span>
<span class="hljs-built_in">Object</span>.prototype == &#123;&#125;.__proto__ <span class="hljs-comment">// true</span>
<span class="hljs-built_in">Array</span>.prototype == [].__proto__ <span class="hljs-comment">// true</span>
<span class="hljs-built_in">Array</span>.prototype == &#123;&#125;.__proto__ <span class="hljs-comment">// false</span></code></pre></div>
<h4 id="回到顶部-20"><a href="#回到顶部-20" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="自动分号"><a href="#自动分号" class="headerlink" title="自动分号"></a>自动分号</h2><p>有时 JavaScript 会自动为代码行补上缺失的分号，即自动分号插入（Automatic SemicolonInsertion，ASI）。<br><br>因为如果缺失了必要的 ; ，代码将无法运行，语言的容错性也会降低。ASI 能让我们忽略那些不必要的 ; 。<br><br>请注意，ASI 只在换行符处起作用，而不会在代码行的中间插入分号。<br><br>如果 JavaScript 解析器发现代码行可能因为缺失分号而导致错误，那么它就会自动补上分<br>号。并且，只有在代码行末尾与换行符之间除了空格和注释之外没有别的内容时，它才会<br>这样做。</p>
<h4 id="回到顶部-21"><a href="#回到顶部-21" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="浮点数精度"><a href="#浮点数精度" class="headerlink" title="浮点数精度"></a>浮点数精度</h2><p><a href="https://www.css88.com/archives/7340" target="_blank" rel="noopener">https://www.css88.com/archives/7340</a></p>
<h4 id="回到顶部-22"><a href="#回到顶部-22" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="cookie、session、localStorage、sessionStorage区别"><a href="#cookie、session、localStorage、sessionStorage区别" class="headerlink" title="cookie、session、localStorage、sessionStorage区别"></a>cookie、session、localStorage、sessionStorage区别</h2><table>
<thead>
<tr>
<th>特性</th>
<th>cookie</th>
<th>localStorage</th>
<th>sessionStorage</th>
</tr>
</thead>
<tbody><tr>
<td>由谁初始化</td>
<td>客户端或服务器，服务器可以使用<code>Set-Cookie</code>请求头。</td>
<td>客户端</td>
<td>客户端</td>
</tr>
<tr>
<td>数据的生命周期</td>
<td>一般由服务器生成，可设置失效时间，如果在浏览器生成，默认是关闭浏览器之后失效</td>
<td>永久保存，可清除</td>
<td>仅在当前会话有效，关闭页面后清除</td>
</tr>
<tr>
<td>存放数据大小</td>
<td>4KB</td>
<td>5MB</td>
<td>5MB</td>
</tr>
<tr>
<td>与服务器通信</td>
<td>每次都会携带在HTTP头中，如果使用cookie保存过多数据会带来性能问题</td>
<td>仅在客户端保存</td>
<td>仅在客户端保存</td>
</tr>
<tr>
<td>用途</td>
<td>一般由服务器生成，用于标识用户身份</td>
<td>用于浏览器缓存数据</td>
<td>用于浏览器缓存数据</td>
</tr>
<tr>
<td>访问权限</td>
<td>任意窗口</td>
<td>任意窗口</td>
<td>当前页面窗口</td>
</tr>
</tbody></table>
<h4 id="回到顶部-23"><a href="#回到顶部-23" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="自执行函数-用于什么场景？好处"><a href="#自执行函数-用于什么场景？好处" class="headerlink" title="自执行函数?用于什么场景？好处?"></a>自执行函数?用于什么场景？好处?</h2><p>自执行函数:1、声明一个匿名函数2、马上调用这个匿名函数。<br><br>作用：创建一个独立的作用域。&lt;b</p>
<p>好处：防止变量弥散到全局，以免各种js库冲突。隔离作用域避免污染，或者截断作用域链，避免闭包造成引用变量无法释放。利用立即执行特性，返回需要的业务函数或对象，避免每次通过条件判断来处理<br></p>
<p>场景：一般用于框架、插件等场景</p>
<h4 id="回到顶部-24"><a href="#回到顶部-24" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="多个页面之间如何进行通信"><a href="#多个页面之间如何进行通信" class="headerlink" title="多个页面之间如何进行通信"></a>多个页面之间如何进行通信</h2><p>有如下几个方式：</p>
<ul>
<li>cookie</li>
<li>web worker</li>
<li>localeStorage和sessionStorage</li>
</ul>
<h4 id="回到顶部-25"><a href="#回到顶部-25" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="css动画和js动画的差异"><a href="#css动画和js动画的差异" class="headerlink" title="css动画和js动画的差异"></a>css动画和js动画的差异</h2><ol>
<li>代码复杂度，js 动画代码相对复杂一些</li>
<li>动画运行时，对动画的控制程度上，js 能够让动画，暂停，取消，终止，css动画不能添加事件</li>
<li>动画性能看，js 动画多了一个js 解析的过程，性能不如 css 动画好</li>
</ol>
<p><a href="https://zhuanlan.zhihu.com/p/41479807" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/41479807</a></p>
<h4 id="回到顶部-26"><a href="#回到顶部-26" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="如何实现文件断点续传"><a href="#如何实现文件断点续传" class="headerlink" title="如何实现文件断点续传"></a>如何实现文件断点续传</h2><p>断点续传最核心的内容就是把文件“切片”然后再一片一片的传给服务器，但是这看似简单的上传过程却有着无数的坑。</p>
<p>首先是文件的识别，一个文件被分成了若干份之后如何告诉服务器你切了多少块，以及最终服务器应该如何把你上传上去的文件进行合并，这都是要考虑的。</p>
<p>因此在文件开始上传之前，我们和服务器要有一个“握手”的过程，告诉服务器文件信息，然后和服务器约定切片的大小，当和服务器达成共识之后就可以开始后续的文件传输了。</p>
<p>前台要把每一块的文件传给后台，成功之后前端和后端都要标识一下，以便后续的断点。</p>
<p>当文件传输中断之后用户再次选择文件就可以通过标识来判断文件是否已经上传了一部分，如果是的话，那么我们可以接着上次的进度继续传文件，以达到续传的功能。<br>有了HTML5 的 File api之后切割文件比想想的要简单的多的多。</p>
<p>只要用slice 方法就可以了</p>
<div class="hljs"><pre><code class="hljs delphi"><span class="hljs-keyword">var</span> packet = <span class="hljs-keyword">file</span>.slice(start, <span class="hljs-keyword">end</span>);</code></pre></div>
<p>参数start是开始切片的位置，end是切片结束的位置 单位都是字节。通过控制start和end 就可以是实现文件的分块</p>
<p>如</p>
<div class="hljs"><pre><code class="hljs angelscript">file.slice(<span class="hljs-number">0</span>,<span class="hljs-number">1000</span>);
file.slice(<span class="hljs-number">1000</span>,<span class="hljs-number">2000</span>);
file.slice(<span class="hljs-number">2000</span>,<span class="hljs-number">3000</span>);
<span class="hljs-comment">// ......</span></code></pre></div>
<p>在把文件切成片之后，接下来要做的事情就是把这些碎片传到服务器上。<br>如果中间掉线了，下次再传的时候就得先从服务器获取上一次上传文件的位置，然后以这个位置开始上传接下来的文件内容。</p>
<p><a href="https://www.cnblogs.com/zhwl/p/3580776.html" target="_blank" rel="noopener">https://www.cnblogs.com/zhwl/p/3580776.html</a></p>
<h4 id="回到顶部-27"><a href="#回到顶部-27" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="new一个对象经历了什么"><a href="#new一个对象经历了什么" class="headerlink" title="new一个对象经历了什么"></a>new一个对象经历了什么</h2><p>创建对象有多少种方式？</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stu</span>(<span class="hljs-params">name,age</span>)</span>&#123;
    <span class="hljs-keyword">let</span> obj = &#123;&#125;
    obj.name=name;
    obj.age = age;
    <span class="hljs-keyword">return</span> obj
&#125;
<span class="hljs-keyword">let</span> s1 = stu()

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stu</span>(<span class="hljs-params">name,age</span>)</span>&#123;
    <span class="hljs-keyword">this</span>.name = name
    <span class="hljs-keyword">this</span>.age = age
&#125;
<span class="hljs-keyword">let</span> s1 = <span class="hljs-keyword">new</span> stu()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">stu</span></span>&#123;
    <span class="hljs-keyword">constructor</span>(name,age)&#123;
        <span class="hljs-keyword">this</span>.name = name
    	<span class="hljs-keyword">this</span>.age = age
    &#125;
&#125;</code></pre></div>



<div class="hljs"><pre><code class="hljs actionscript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Test</span><span class="hljs-params">()</span></span>&#123;&#125;
<span class="hljs-keyword">const</span> test = <span class="hljs-keyword">new</span> Test()</code></pre></div>

<ol>
<li>创建一个新对象：<div class="hljs"><pre><code class="hljs actionscript"><span class="hljs-keyword">const</span> obj = &#123;&#125;</code></pre></div></li>
<li>设置新对象的constructor属性为构造函数的名称，设置新对象的<strong>proto</strong>属性指向构造函数的prototype对象<div class="hljs"><pre><code class="hljs delphi">obj<span class="hljs-function">.<span class="hljs-keyword">constructor</span> = <span class="hljs-title">Test</span></span>
<span class="hljs-function"><span class="hljs-title">obj</span>.__<span class="hljs-title">proto__</span> = <span class="hljs-title">Test</span>.<span class="hljs-title">prototype</span></span></code></pre></div></li>
<li>使用新对象调用函数，函数中的this被指向新实例对象<div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Test</span>.</span></span>call(obj)</code></pre></div></li>
<li>将初始化完毕的新对象地址，保存到等号左边的变量中</li>
</ol>
<h2 id="bind、call、apply、箭头函数、new的区别"><a href="#bind、call、apply、箭头函数、new的区别" class="headerlink" title="bind、call、apply、箭头函数、new的区别"></a>bind、call、apply、箭头函数、new的区别</h2><p>call和apply其实是一样的，区别就在于传参时参数是一个一个传或者是以一个数组的方式来传。<br><br>call和apply都是在调用时生效，改变调用者的this指向。<br></p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">let</span> name = <span class="hljs-string">'Jack'</span>
<span class="hljs-keyword">const</span> obj = &#123;<span class="hljs-attr">name</span>: <span class="hljs-string">'Tom'</span>&#125;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHi</span>(<span class="hljs-params"></span>) </span>&#123;<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hi! '</span> + <span class="hljs-keyword">this</span>.name)&#125;

sayHi() <span class="hljs-comment">// Hi! Jack</span>
sayHi.call(obj) <span class="hljs-comment">// Hi! Tom</span></code></pre></div>
<p>bind也是改变this指向，不过不是在调用时生效，而是返回一个新函数。</p>
<div class="hljs"><pre><code class="hljs haxe">const <span class="hljs-keyword">new</span><span class="hljs-type">Func</span> = sayHi.bind(obj)
<span class="hljs-keyword">new</span><span class="hljs-type">Func</span>() <span class="hljs-comment">// Hi! Tom</span></code></pre></div>
<h4 id="-2"><a href="#-2" class="headerlink" title=""></a></h4><h2 id="请简述JavaScript中的this。"><a href="#请简述JavaScript中的this。" class="headerlink" title="请简述JavaScript中的this。"></a>请简述<code>JavaScript</code>中的<code>this</code>。</h2><p>JS 中的<code>this</code>是一个相对复杂的概念，不是简单几句能解释清楚的。粗略地讲，函数的调用方式决定了<code>this</code>的值。我阅读了网上很多关于<code>this</code>的文章，<a href="https://medium.com/@arnav_aggarwal" target="_blank" rel="noopener">Arnav Aggrawal</a> 写的比较清楚。<code>this</code>取值符合以下规则：</p>
<ol>
<li>在调用函数时使用<code>new</code>关键字，函数内的<code>this</code>是一个全新的对象。</li>
<li>如果<code>apply</code>、<code>call</code>或<code>bind</code>方法用于调用、创建一个函数，函数内的 this 就是作为参数传入这些方法的对象。</li>
<li>当函数作为对象里的方法被调用时，函数内的<code>this</code>是调用该函数的对象。比如当<code>obj.method()</code>被调用时，函数内的 this 将绑定到<code>obj</code>对象。</li>
<li>如果调用函数不符合上述规则，那么<code>this</code>的值指向全局对象（global object）。浏览器环境下<code>this</code>的值指向<code>window</code>对象，但是在严格模式下(<code>&#39;use strict&#39;</code>)，<code>this</code>的值为<code>undefined</code>。</li>
<li>如果符合上述多个规则，则较高的规则（1 号最高，4 号最低）将决定<code>this</code>的值。</li>
<li>如果该函数是 ES2015 中的箭头函数，将忽略上面的所有规则，<code>this</code>被设置为它被创建时的上下文。</li>
</ol>
<p>想获得更深入的解释，请查看<a href="https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3" target="_blank" rel="noopener">他在 Medium 上的文章</a>。</p>
<p><a href="https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Chinese/questions/javascript-questions.md#%E8%AF%B7%E7%AE%80%E8%BF%B0javascript%E4%B8%AD%E7%9A%84this" target="_blank" rel="noopener">https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Chinese/questions/javascript-questions.md#%E8%AF%B7%E7%AE%80%E8%BF%B0javascript%E4%B8%AD%E7%9A%84this</a></p>
<h4 id="回到顶部-28"><a href="#回到顶部-28" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="如何确定this指向"><a href="#如何确定this指向" class="headerlink" title="如何确定this指向"></a>如何确定this指向</h2><p>如果要判断一个运行中函数的 this 绑定，就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断 this 的绑定对象。</p>
<ol>
<li>由 new 调用？绑定到新创建的对象。</li>
<li>由 call 或者 apply （或者 bind ）调用？绑定到指定的对象。</li>
<li>由上下文对象调用？绑定到那个上下文对象。</li>
<li>默认：在严格模式下绑定到 undefined ，否则绑定到全局对象。</li>
</ol>
<p>一定要注意，有些调用可能在无意中使用默认绑定规则。如果想“更安全”地忽略 this 绑定，你可以使用一个 DMZ 对象，比如 ø = Object.create(null) ，以保护全局对象。<br><br>ES6 中的箭头函数并不会使用四条标准的绑定规则，而是根据当前的词法作用域来决定this ，具体来说，箭头函数会继承外层函数调用的 this 绑定（无论 this 绑定到什么）。这其实和 ES6 之前代码中的 self = this 机制一样</p>
<p>参考：《你不知道的JavaScript》</p>
<h4 id="回到顶部-29"><a href="#回到顶部-29" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="和-的区别是什么"><a href="#和-的区别是什么" class="headerlink" title="==和===的区别是什么"></a>==和===的区别是什么</h2><p><code>==</code>是抽象相等运算符，而<code>===</code>是严格相等运算符。<code>==</code>运算符是在进行必要的类型转换后，再比较。<code>===</code>运算符不会进行类型转换，所以如果两个值不是相同的类型，会直接返回<code>false</code>。使用<code>==</code>时，可能发生一些特别的事情，例如：</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-number">1</span> == <span class="hljs-string">'1'</span>; <span class="hljs-comment">// true</span>
<span class="hljs-number">1</span> == [<span class="hljs-number">1</span>]; <span class="hljs-comment">// true</span>
<span class="hljs-number">1</span> == <span class="hljs-literal">true</span>; <span class="hljs-comment">// true</span>
<span class="hljs-number">0</span> == <span class="hljs-string">''</span>; <span class="hljs-comment">// true</span>
<span class="hljs-number">0</span> == <span class="hljs-string">'0'</span>; <span class="hljs-comment">// true</span>
<span class="hljs-number">0</span> == <span class="hljs-literal">false</span>; <span class="hljs-comment">// true</span></code></pre></div>
<p>如果你对<code>==</code>和<code>===</code>的概念不是特别了解，建议大多数情况下使用<code>===</code></p>
<h4 id="回到顶部-30"><a href="#回到顶部-30" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="箭头函数和普通函数有什么区别"><a href="#箭头函数和普通函数有什么区别" class="headerlink" title="箭头函数和普通函数有什么区别"></a>箭头函数和普通函数有什么区别</h2><ul>
<li>函数体内的<code>this</code>对象，就是定义时所在的对象，而不是使用时所在的对象，用<code>call</code> <code>apply</code> <code>bind</code>也不能改变<code>this</code>指向</li>
<li>不可以当作构造函数，也就是说，不可以使用<code>new</code>命令，否则会抛出一个错误。</li>
<li>不可以使用<code>arguments</code>对象，该对象在函数体内不存在。如果要用，可以用 <code>rest</code> 参数代替。</li>
<li>不可以使用<code>yield</code>命令，因此箭头函数不能用作 <code>Generator</code> 函数。</li>
<li>箭头函数没有原型对象<code>prototype</code></li>
</ul>
<h4 id="回到顶部-31"><a href="#回到顶部-31" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="首屏时间、白屏时间"><a href="#首屏时间、白屏时间" class="headerlink" title="首屏时间、白屏时间"></a>首屏时间、白屏时间</h2><p>Performance 接口可以获取到当前页面中与性能相关的信息。<br><br>该类型的对象可以通过调用只读属性 Window.performance 来获得。<br><br>白屏时间：</p>
<div class="hljs"><pre><code class="hljs css"><span class="hljs-selector-tag">performance</span><span class="hljs-selector-class">.timing</span><span class="hljs-selector-class">.responseStart</span> <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">performance</span><span class="hljs-selector-class">.timing</span><span class="hljs-selector-class">.navigationStart</span></code></pre></div>
<p>首屏时间</p>
<div class="hljs"><pre><code class="hljs coffeescript"><span class="hljs-built_in">window</span>.onload = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> &#123;
    <span class="hljs-keyword">new</span> Date() - performance.timing.responseStart
&#125;</code></pre></div>
<p><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Performance" target="_blank" rel="noopener">https://developer.mozilla.org/zh-CN/docs/Web/API/Performance</a></p>
<h2 id="当你在浏览器输入一个地址后发生了什么"><a href="#当你在浏览器输入一个地址后发生了什么" class="headerlink" title="当你在浏览器输入一个地址后发生了什么"></a>当你在浏览器输入一个地址后发生了什么</h2><h3 id="页面大量图片，如何优化加载，优化用户体验"><a href="#页面大量图片，如何优化加载，优化用户体验" class="headerlink" title="页面大量图片，如何优化加载，优化用户体验"></a>页面大量图片，如何优化加载，优化用户体验</h3><ol>
<li>图片懒加载。在页面的未可视区域添加一个滚动事件，判断图片位置与浏览器顶端的距离与页面的距离，如果前者小于后者，优先加载。</li>
<li>如果为幻灯片、相册等，可以使用图片预加载技术，将当前展示图片的前一张和后一张优先下载。</li>
<li>如果图片为css图片，可以使用CSSsprite，SVGsprite等技术。</li>
<li>如果图片过大，可以使用特殊编码的图片，加载时会先加载一张压缩的特别厉害的缩略图，以提高用户体验。</li>
<li>如果图片展示区域小于图片的真实大小，应在服务器端根据业务需要先进行图片压缩，图片压缩后大小与展示一致。</li>
</ol>
<h4 id="-3"><a href="#-3" class="headerlink" title=""></a></h4><h2 id="js网络请求性能优化之防抖与节流"><a href="#js网络请求性能优化之防抖与节流" class="headerlink" title="js网络请求性能优化之防抖与节流"></a>js网络请求性能优化之防抖与节流</h2><ul>
<li><p>防抖(debounce)<br><br>在函数需要频繁触发时，只有当有足够空闲的时间时，才执行一次。就好像在百度搜索时，每次输入之后都有联想词弹出，这个控制联想词的方法就不可能是输入框内容一改变就触发的，他一定是当你结束输入一段时间之后才会触发。</p>
</li>
<li><p>节流(thorttle)<br><br>预定一个函数只有在大于等于执行周期时才执行，周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时，你不断点刷新点购买，可是总有一段时间你点上是没有效果，这里就用到了节流，就是怕点的太快导致系统出现bug。</p>
</li>
<li><p>区别<br><br>在发生持续触发事件时，防抖设置事件延迟并在空闲时间去触发事件，而节流则是隔一定的时间触发一次。</p>
</li>
</ul>
<p>具体请看：<br><br><a href="https://blog.csdn.net/jacoox/article/details/80719456" target="_blank" rel="noopener">https://blog.csdn.net/jacoox/article/details/80719456</a></p>
<h4 id="回到顶部-32"><a href="#回到顶部-32" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="history，路由模式原理-如何做到修改url参数页面不刷新"><a href="#history，路由模式原理-如何做到修改url参数页面不刷新" class="headerlink" title="history，路由模式原理,如何做到修改url参数页面不刷新"></a>history，路由模式原理,如何做到修改url参数页面不刷新</h2><p>HTML5引入了 <code>history.pushState()</code> 和 <code>history.replaceState()</code> 方法，它们分别可以添加和修改历史记录条目。</p>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-keyword">let</span> stateObj = &#123;
    foo: <span class="hljs-string">"bar"</span>,
&#125;;

history.pushState(stateObj, <span class="hljs-string">"page 2"</span>, <span class="hljs-string">"bar.html"</span>);</code></pre></div>
<p>假设当前页面为 <code>foo.html</code>，执行上述代码后会变为 <code>bar.html</code>，点击浏览器后退，会变为 <code>foo.html</code>，但浏览器并不会刷新。<br><code>pushState()</code> 需要三个参数: 一个状态对象, 一个标题 (目前被忽略), 和 (可选的) 一个 URL. 让我们来解释下这三个参数详细内容：</p>
<ul>
<li><p>状态对象 — 状态对象 <code>state</code> 是一个 JavaScript 对象，通过 <code>pushState ()</code> 创建新的历史记录条目。无论什么时候用户导航到新的状态，<code>popstate</code> 事件就会被触发，且该事件的 <code>state</code> 属性包含该历史记录条目状态对象的副本。<br>状态对象可以是能被序列化的任何东西。原因在于 Firefox 将状态对象保存在用户的磁盘上，以便在用户重启浏览器时使用，我们规定了状态对象在序列化表示后有640k的大小限制。如果你给 <code>pushState()</code> 方法传了一个序列化后大于 640k 的状态对象，该方法会抛出异常。如果你需要更大的空间，建议使用 <code>sessionStorage</code> 以及 <code>localStorage</code>.</p>
</li>
<li><p>标题 — Firefox 目前忽略这个参数，但未来可能会用到。传递一个空字符串在这里是安全的，而在将来这是不安全的。二选一的话，你可以为跳转的 <code>state</code> 传递一个短标题。</p>
</li>
<li><p>URL — 该参数定义了新的历史URL记录。注意，调用 <code>pushState()</code> 后浏览器并不会立即加载这个 URL，但可能会在稍后某些情况下加载这个 URL，比如在用户重新打开浏览器时。新URL不必须为绝对路径。如果新URL是相对路径，那么它将被作为相对于当前 URL 处理。新 URL 必须与当前URL同源，否则 <code>pushState()</code> 会抛出一个异常。该参数是可选的，缺省为当前 URL。</p>
</li>
</ul>
<h4 id="回到顶部-33"><a href="#回到顶部-33" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="格式化金钱，每千分位加逗号"><a href="#格式化金钱，每千分位加逗号" class="headerlink" title="格式化金钱，每千分位加逗号"></a>格式化金钱，每千分位加逗号</h2><div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">format</span>(<span class="hljs-params">str</span>) </span>&#123;
    <span class="hljs-keyword">let</span> s = <span class="hljs-string">''</span>
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = str.length - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; i--) &#123;
        s = str[i] + s
        count++
        <span class="hljs-keyword">if</span> (count % <span class="hljs-number">3</span> == <span class="hljs-number">0</span> &amp;&amp; i != <span class="hljs-number">0</span>) &#123;
            s = <span class="hljs-string">','</span> + s
        &#125;
    &#125;
    <span class="hljs-keyword">return</span> s
&#125;</code></pre></div>
<div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">format</span>(<span class="hljs-params">str</span>) </span>&#123;
    <span class="hljs-keyword">return</span> str.replace(<span class="hljs-regexp">/(\d)(?=(?:\d&#123;3&#125;)+$)/g</span>, <span class="hljs-string">'$1,'</span>)
&#125;</code></pre></div>
<h4 id="回到顶部-34"><a href="#回到顶部-34" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="请用js去除字符串空格"><a href="#请用js去除字符串空格" class="headerlink" title="请用js去除字符串空格"></a>请用js去除字符串空格</h2><h3 id="去除所有空格"><a href="#去除所有空格" class="headerlink" title="去除所有空格"></a>去除所有空格</h3><div class="hljs"><pre><code class="hljs arcade">str.replace(<span class="hljs-regexp">/\s/g</span>, <span class="hljs-string">''</span>)</code></pre></div>
<h3 id="去除两边空格"><a href="#去除两边空格" class="headerlink" title="去除两边空格"></a>去除两边空格</h3><div class="hljs"><pre><code class="hljs processing"><span class="hljs-built_in">str</span>.replace(/^\s+|\s+$/g, <span class="hljs-string">''</span>)
<span class="hljs-comment">// 原生方法</span>
<span class="hljs-built_in">str</span>.<span class="hljs-built_in">trim</span>()</code></pre></div>
<h4 id="回到顶部-35"><a href="#回到顶部-35" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="创建对象有几种方法"><a href="#创建对象有几种方法" class="headerlink" title="创建对象有几种方法"></a>创建对象有几种方法</h2><ul>
<li>字面量<div class="hljs"><pre><code class="hljs js"><span class="hljs-keyword">const</span> obj = &#123;<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>&#125;</code></pre></div></li>
<li>构造函数<div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Obj</span>(<span class="hljs-params">val</span>) </span>&#123;
    <span class="hljs-keyword">this</span>.a = val
&#125;

<span class="hljs-keyword">const</span> obj = <span class="hljs-keyword">new</span> Obj(<span class="hljs-number">1</span>)</code></pre></div></li>
<li>Object.create<div class="hljs"><pre><code class="hljs js"><span class="hljs-keyword">const</span> obj = <span class="hljs-built_in">Object</span>.create(&#123;<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>&#125;)</code></pre></div>
<h4 id="回到顶部-36"><a href="#回到顶部-36" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4></li>
</ul>
<h2 id="null和undefined的区别"><a href="#null和undefined的区别" class="headerlink" title="null和undefined的区别"></a>null和undefined的区别</h2><p><code>null</code> 表示一个对象是“没有值”的值，也就是值为“空”</p>
<p><code>undefined</code> 表示一个变量声明了没有初始化(赋值)</p>
<p><code>undefined</code> 和 <code>null</code> 在if语句中，都会被自动转为false</p>
<p><code>undefined</code> 不是一个有效的JSON，而 <code>null</code> 是</p>
<p><code>undefined</code> 的类型(typeof)是 <code>undefined</code></p>
<p><code>null</code> 的类型(typeof)是 <code>object</code></p>
<p>Javascript将未赋值的变量默认值设为 <code>undefined</code></p>
<p>Javascript从来不会将变量设为 <code>null</code>。 它是用来让程序员表明某个用var声明的变量时没有值的</p>
<h4 id="回到顶部-37"><a href="#回到顶部-37" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4><h2 id="反转数组"><a href="#反转数组" class="headerlink" title="反转数组"></a>反转数组</h2><h3 id="要求"><a href="#要求" class="headerlink" title="要求"></a>要求</h3><p><strong>input</strong>: I am a student <br><br><strong>output</strong>: student a am I <br><br>输入是数组 输出也是数组<br><br>不允许用 <code>split</code> <code>splice</code> <code>reverse</code><br></p>
<h4 id="解法一"><a href="#解法一" class="headerlink" title="解法一"></a>解法一</h4><div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reverseArry</span>(<span class="hljs-params">arry</span>) </span>&#123;
    <span class="hljs-keyword">const</span> str = arry.join(<span class="hljs-string">' '</span>)
    <span class="hljs-keyword">const</span> result = []
    <span class="hljs-keyword">let</span> word = <span class="hljs-string">''</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>, len = str.length; i &lt; len; i++) &#123;
	<span class="hljs-keyword">if</span> (str[i] != <span class="hljs-string">' '</span>) &#123;
	    word += str[i]
	&#125; <span class="hljs-keyword">else</span> &#123;
	    result.unshift(word)
	    word = <span class="hljs-string">''</span>
	&#125;
    &#125;

    result.unshift(word)
    <span class="hljs-keyword">return</span> result
&#125;

<span class="hljs-built_in">console</span>.log(reverseArry([<span class="hljs-string">'I'</span>, <span class="hljs-string">'am'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-string">'student'</span>]))
<span class="hljs-comment">// ["student", "a", "am", "I"]</span></code></pre></div>
<h4 id="解法二"><a href="#解法二" class="headerlink" title="解法二"></a>解法二</h4><div class="hljs"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reverseArry</span>(<span class="hljs-params">arry</span>) </span>&#123;
    <span class="hljs-keyword">const</span> result = []
    <span class="hljs-keyword">const</span> distance = arry.length - <span class="hljs-number">1</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = distance; i &gt;= <span class="hljs-number">0</span>; i--) &#123;
        result[distance - i] = arry[i]
    &#125;

    <span class="hljs-keyword">return</span> result
&#125;</code></pre></div>

<h4 id="回到顶部-38"><a href="#回到顶部-38" class="headerlink" title="回到顶部"></a><a href="#JavaScript">回到顶部</a></h4>
            </article>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" target="_blank" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <div class="post-prev col-6">
                    
                    
                      <a href="/blog/2020/06/26/vue/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">vue</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </div>
                  <div class="post-next col-6">
                    
                    
                      <a href="/blog/2020/06/26/HTTP/">
                        <span class="hidden-mobile">HTTP</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </div>
                </div>
              
            </div>

            
              <!-- Comments -->
              <div class="comments" id="comments">
                
                

              </div>
            
          </div>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener">
        <span>Fluid</span></a>
    </div>
    

    

    
  </div>
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/blog/js/debouncer.js" ></script>
<script  src="/blog/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/blog/js/lazyload.js" ></script>
  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/blog/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: 'article.markdown-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "JavaSciprt&nbsp;",
      ],
      cursorChar: "|",
      typeSpeed: 70,
      loop: true,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/blog/js/local-search.js" ></script>
  <script>
    var path = "/blog/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>







  
  
    <script>
      !function (e, t, a) {
        function r() {
          for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x + "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e].scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
          requestAnimationFrame(r)
        }

        function n() {
          var t = "function" == typeof e.onclick && e.onclick;
          e.onclick = function (e) {
            t && t(), o(e)
          }
        }

        function o(e) {
          var a = t.createElement("div");
          a.className = "heart", s.push({
            el: a,
            x: e.clientX - 5,
            y: e.clientY - 5,
            scale: 1,
            alpha: 1,
            color: c()
          }), t.body.appendChild(a)
        }

        function i(e) {
          var a = t.createElement("style");
          a.type = "text/css";
          try {
            a.appendChild(t.createTextNode(e))
          } catch (t) {
            a.styleSheet.cssText = e
          }
          t.getElementsByTagName("head")[0].appendChild(a)
        }

        function c() {
          return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
        }

        var s = [];
        e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
          setTimeout(e, 1e3 / 60)
        }, i(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"), n(), r()
      }(window, document);
    </script>
  













</body>
</html>
